package com.treeman.user.dao;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.treeman.friend.Invitation;
import com.treeman.user.User;

@Repository
public class UserDaoImpl implements UserDao {

	private static Logger log = Logger.getLogger(UserDaoImpl.class);

	private SessionFactory sessionFactory;

	@Autowired
	public UserDaoImpl(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	private Session currentSession() {
		return sessionFactory.getCurrentSession();
	}

	@Override
	public Long addUser(User user) {
		return (Long) currentSession().save(user);
	}

	@Override
	public User getUserById(Long id) {
		return (User) currentSession().get(User.class, id);
	}

	@Override
	public User getUserByUsername(String username) {
		return (User) currentSession().createCriteria(User.class)
				.setFetchMode("userRoles", FetchMode.JOIN)
				.add(Restrictions.eq("username", username)).uniqueResult();
	}

	@Override
	public void updateUser(User user) {
		currentSession().update(user);
	}

	@Override
	public List<User> findUsers(String firstname, String lastname,
			String username) {

		Map<String, String> params = new HashMap<String, String>();
		if (firstname != null && !firstname.trim().equals(""))
			params.put("userAdditionalInformations.firstName", firstname);
		if (lastname != null && !lastname.trim().equals(""))
			params.put("userAdditionalInformations.lastName", lastname);
		if (username != null && !username.trim().equals(""))
			params.put("username", username);

		Criteria criteria = currentSession().createCriteria(User.class);
		for (String key : params.keySet()) {
			String value = params.get(key);
			criteria.add(Restrictions.ilike(key, value + "%"));
		}

		@SuppressWarnings("unchecked")
		List<User> result = criteria.list();

		return result;
	}

	@Override
	public Set<User> getUserFriends(String username) {
		User user = (User) currentSession().createCriteria(User.class)
				.setFetchMode("friends", FetchMode.JOIN)
				.add(Restrictions.eq("username", username)).uniqueResult();
		return user.getFriends();
	}

	@Override
	public Set<Invitation> getReceivedInvitations(String username) {

		User user = (User) currentSession().createCriteria(User.class)
				.setFetchMode("recievedInvitations", FetchMode.JOIN)
				.add(Restrictions.eq("username", username)).uniqueResult();

		return user.getRecievedInvitations();
	}

	@Override
	public void removeInvitation(User from, User to) {
		currentSession().delete(new Invitation(from, to));
	}

	@Override
	public Boolean isAlreadyInvited(User user1, User user2) {

		Invitation inv1 = (Invitation) currentSession().get(Invitation.class,
				new Invitation(user1, user2));
		if (inv1 != null)
			return true;
		Invitation inv2 = (Invitation) currentSession().get(Invitation.class,
				new Invitation(user2, user1));
		return (inv2 != null);
	}

}
